/*
 * slf4log4cxx.h
 *
 *  Created on: 17/01/2013
 *      Author: Jeffrey Alvarez Masson
 */

#ifndef SLF4LOG4CXX_H_
#define SLF4LOG4CXX_H_

#include "ilogger.h"
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>
#include <cstdio>

namespace slf4cxx {

/**
 * Logging class wrapper for log4cxx.
 */
class Slf4log4cxx : public slf4cxx::ILogger {
private:
	std::string ip;
	log4cxx::LoggerPtr logger;

	/**
	 * Get the log4cxx level equivalent to the slf4cxx log level.
	 * @param logLevel slf4cxx log level to get the log4cxx equivalent level.
	 */
	log4cxx::LevelPtr toLog4CxxLevel(ILogger::ILoggerLevel logLevel) {
		static const log4cxx::LevelPtr LoggerLevels[5] = {
				log4cxx::Level::getDebug(),
				log4cxx::Level::getInfo (),
				log4cxx::Level::getWarn (),
				log4cxx::Level::getError (),
				log4cxx::Level::getFatal ()
		};
		return LoggerLevels[(int)logLevel];
	}

public:
	/**
	 * Create a new instance of the Slf4log4cxx class.
	 * @param configFileName Configuration file name.
	 */
	Slf4log4cxx(std::string configFileName) : slf4cxx::ILogger() {
		log4cxx::PropertyConfigurator::configure(configFileName);
		logger = log4cxx::Logger::getRootLogger();
		this->ip = "";
	}

	/**
	 * Deallocates resources.
	 */
	virtual ~Slf4log4cxx() {}

	/**
	 * Set logging level.
	 * @param logLevel Logging level to set.
	 */
	virtual void setLevel(ILogger::ILoggerLevel logLevel) {
		logger->setLevel(toLog4CxxLevel(logLevel));
	}

	/**
	 * Create and write a log entry.
	 * @param logLevel Level of the entry.
	 * @param format Format of the entry to create. Additional arguments are permitted for substitution.
	 */
	virtual void log(ILogger::ILoggerLevel logLevel, const char* format, ...) {
		using namespace std;
		va_list va;
		va_start(va, format);
		char logMessage[200];
		vsprintf(logMessage, format, va);
		va_end(va);

		string ipToWrite;
		if (!this->ip.empty())
			ipToWrite = "(" + ip + ") ";

		stringstream ssoutput;
		ssoutput << ip << logMessage;
		string output = ssoutput.str();
		log4cxx::LevelPtr level = toLog4CxxLevel(logLevel);

		logger->log(level, logMessage);
	}

	/**
	 * Sets an IP to be written in each entry.
	 * @param ip IP to be written in each log entry. Set to empty to avoid writing the IP.
	 */
	void setIP(std::string ip) {
		this->ip = ip;
	}
};

} /* namespace slf4cxx */
#endif /* SLF4LOG4CXX_H_ */
